package com.bytedance.retrofit2;

import com.bytedance.retrofit2.client.Client;
import com.bytedance.retrofit2.client.SsResponse;
import com.bytedance.retrofit2.http.DELETE;
import com.bytedance.retrofit2.http.FormUrlEncoded;
import com.bytedance.retrofit2.http.GET;
import com.bytedance.retrofit2.http.HEAD;
import com.bytedance.retrofit2.http.HTTP;
import com.bytedance.retrofit2.http.Headers;
import com.bytedance.retrofit2.http.Multipart;
import com.bytedance.retrofit2.http.OPTIONS;
import com.bytedance.retrofit2.http.PATCH;
import com.bytedance.retrofit2.http.POST;
import com.bytedance.retrofit2.http.PUT;
import com.bytedance.retrofit2.http.Priority;
import com.bytedance.retrofit2.http.Streaming;

import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executor;

public final class Retrofit {
    final Client.Provider clientProvider;
    final HttpUrl baseUrl;
    final List<Converter.Factory> converterFactories;
    final List<CallAdapter.Factory> adapterFactories;
    final Executor httpExecutor;
    final RequestInterceptor requestInterceptor;
    final ResponseInterceptor responseInterceptor;
    private final Map serviceMethodCache = new LinkedHashMap();

    public Retrofit(HttpUrl baseUrl, Client.Provider clientProvider,
                    RequestInterceptor requestInterceptor, ResponseInterceptor responseInterceptor,
                    List converterFactories, List adapterFactories, Executor httpExecutor) {
        this.baseUrl = baseUrl;
        this.clientProvider = clientProvider;
        this.requestInterceptor = requestInterceptor;
        this.responseInterceptor = responseInterceptor;
        this.converterFactories = Collections.unmodifiableList(converterFactories);
        this.adapterFactories = Collections.unmodifiableList(adapterFactories);
        this.httpExecutor = httpExecutor;
    }

    public final Converter toStringConverter(Type type, Annotation[] annotations) {
        Utils.checkNotNull(type, "type == null");
        Utils.checkNotNull(annotations, "annotations == null");
        int size = this.converterFactories.size();
        for (int i = 0; i < size; ++i) {
            Converter converter = this.converterFactories.get(i).findToStringConverter(type);
            if (converter != null) {
                return converter;
            }
        }
        throw new IllegalArgumentException("Could not locate object converter");
    }

    public final Converter requestBodyConverter(Type arg6, Annotation[] arg7, Annotation[] arg8) {
        Utils.checkNotNull(arg6, "type == null");
        Utils.checkNotNull(arg7, "parameterAnnotations == null");
        Utils.checkNotNull(arg8, "methodAnnotations == null");
        int v1 = this.converterFactories.indexOf(null) + 1;
        int v3 = this.converterFactories.size();
        int v2;
        for (v2 = v1; v2 < v3; ++v2) {
            Converter v0 = this.converterFactories.get(v2).a(arg6);
            if (v0 != null) {
                return v0;
            }
        }

        StringBuilder v2_1 = new StringBuilder("Could not locate RequestBody converter for ").append(arg6).append(".\n");
        v2_1.append("  Tried:");
        v3 = this.converterFactories.size();
        while (v1 < v3) {
            v2_1.append("\n   * ").append(this.converterFactories.get(v1).getClass().getName());
            ++v1;
        }

        throw new IllegalArgumentException(v2_1.toString());
    }

    final ServiceMethod loadServiceMethod(Method arg10) {
        ServiceMethod v0_1;
        Map v3 = this.serviceMethodCache;
        synchronized (v3) {
            v0_1 = (ServiceMethod) this.serviceMethodCache.get(arg10);
            if (v0_1 == null) {
                ServiceMethod.Builder v4 = new ServiceMethod.Builder(this, arg10);
                v4.callAdapter = v4.createCallAdapter();
                v4.responseType = v4.callAdapter.responseType();
                if (v4.responseType == SsResponse.class) {
                    throw v4.methodError(null, "\'" + Utils.getRawType(v4.responseType).getName() + "\' is not a valid response body type.", new Object[0]);
                } else {
                    v4.responseConverter = v4.createResponseConverter();
                    Annotation[] v5 = v4.methodAnnotations;
                    int v6 = v5.length;
                    int v2;
                    for (v2 = 0; v2 < v6; ++v2) {
                        Annotation v0_2 = v5[v2];
                        if ((v0_2 instanceof DELETE)) {
                            v4.parseHttpMethodAndPath("DELETE", ((DELETE) v0_2).a(), false);
                        } else if ((v0_2 instanceof GET)) {
                            v4.parseHttpMethodAndPath("GET", ((GET) v0_2).a(), false);
                        } else if ((v0_2 instanceof HEAD)) {
                            v4.parseHttpMethodAndPath("HEAD", ((HEAD) v0_2).a(), false);
                            if (!Void.class.equals(v4.responseType)) {
                                throw v4.methodError(null, "HEAD method must use Void as response type.", new Object[0]);
                            }
                        } else if ((v0_2 instanceof PATCH)) {
                            v4.parseHttpMethodAndPath("PATCH", ((PATCH) v0_2).a(), true);
                        } else if ((v0_2 instanceof POST)) {
                            v4.parseHttpMethodAndPath("POST", ((POST) v0_2).a(), true);
                        } else if ((v0_2 instanceof PUT)) {
                            v4.parseHttpMethodAndPath("PUT", ((PUT) v0_2).a(), true);
                        } else if ((v0_2 instanceof OPTIONS)) {
                            v4.parseHttpMethodAndPath("OPTIONS", ((OPTIONS) v0_2).a(), false);
                        } else if ((v0_2 instanceof HTTP)) {
                            v4.parseHttpMethodAndPath(((HTTP) v0_2).a(), ((HTTP) v0_2).b(), ((HTTP) v0_2).c());
                        } else if ((v0_2 instanceof Headers)) {
                            String[] v0_3 = ((Headers) v0_2).a();
                            if (v0_3.length == 0) {
                                throw v4.methodError(null, "@Headers annotation is empty.", new Object[0]);
                            } else {
                                v4.headers = v4.parseHeaders(v0_3);
                            }
                        } else if ((v0_2 instanceof Multipart)) {
                            if (v4.isFormEncoded) {
                                throw v4.methodError(null, "Only one encoding annotation is allowed.", new Object[0]);
                            } else {
                                v4.isMultipart = true;
                            }
                        } else if ((v0_2 instanceof FormUrlEncoded)) {
                            if (v4.isMultipart) {
                                throw v4.methodError(null, "Only one encoding annotation is allowed.", new Object[0]);
                            } else {
                                v4.isFormEncoded = true;
                            }
                        } else if ((v0_2 instanceof Streaming)) {
                            v4.isStreaming = true;
                        } else if ((v0_2 instanceof Priority)) {
                            v4.priorityLevel = ((Priority) v0_2).a();
                        }
                    }

                    if (v4.httpMethod == null) {
                        throw v4.methodError(null, "HTTP method annotation is required (e.g., @GET, @POST, etc.).", new Object[0]);
                    }

                    if (!v4.hasBody && !v4.notNull) {
                        if (v4.isMultipart) {
                            throw v4.methodError(null, "Multipart can only be specified on HTTP methods with request body (e.g., @POST).", new Object[0]);
                        } else if (v4.isFormEncoded) {
                            throw v4.methodError(null, "FormUrlEncoded can only be specified on HTTP methods with request body (e.g., @POST).", new Object[0]);
                        }
                    }

                    v2 = v4.parameterAnnotationsArray.length;
                    v4.parameterHandlers = new ParameterHandler[v2];
                    int v0_4;
                    for (v0_4 = 0; v0_4 < v2; ++v0_4) {
                        Type v1 = v4.parameterTypes[v0_4];
                        if (Utils.hasUnresolvableType(v1)) {
                            throw v4.parameterError(v0_4, "Parameter type must not include a type variable or wildcard: %s", new Object[]{v1});
                        }

                        v5 = v4.parameterAnnotationsArray[v0_4];
                        if (v5 == null) {
                            throw v4.parameterError(v0_4, "No Retrofit annotation found.", new Object[0]);
                        }

                        v4.parameterHandlers[v0_4] = v4.parseParameter(v0_4, v1, v5);
                    }

                    if (v4.relativeUrl == null && !v4.gotUrl) {
                        throw v4.methodError(null, "Missing either @%s URL or @Url parameter.", new Object[]{v4.httpMethod});
                    }

                    if (!v4.isFormEncoded && !v4.isMultipart && !v4.hasBody && !v4.notNull && (v4.gotBody)) {
                        throw v4.methodError(null, "Non-body HTTP method cannot contain @Body.", new Object[0]);
                    }

                    if ((v4.isFormEncoded) && !v4.gotField) {
                        throw v4.methodError(null, "Form-encode method must contain at least one @Field.", new Object[0]);
                    }

                    if ((v4.isMultipart) && !v4.gotPart) {
                        throw v4.methodError(null, "Multipart method must contain at least one @Part.", new Object[0]);
                    }

                    v0_1 = new ServiceMethod(v4);
                    this.serviceMethodCache.put(arg10, v0_1);
                }
            }
            return v0_1;
        }
    }

    public final <T> T create(Class<T> service) {
        Utils.validateServiceInterface(service);
        return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class[]{service}, new InvocationHandler() {
            @Override
            public final Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                if (method.getDeclaringClass() == Object.class) {
                    return method.invoke(this, args);
                } else {
                    Platform.isDefaultMethod();
                    ServiceMethod serviceMethod = loadServiceMethod(method);
                    SsCall ssHttpCall = new SsCall(serviceMethod, args);
                    return serviceMethod.callAdapter.adapt(ssHttpCall);
                }
            }
        });
    }

    public final Converter stringConverter(Type arg4, Annotation[] arg5) {
        Converter v0;
        Utils.checkNotNull(arg4, "type == null");
        Utils.checkNotNull(arg5, "annotations == null");
        int v2 = this.converterFactories.size();
        int v1 = 0;
        while (true) {
            if (v1 < v2) {
                v0 = this.converterFactories.get(v1).c(arg4);
                if (v0 == null) {
                    ++v1;
                    continue;
                }
            } else {
                break;
            }

            return v0;
        }
        return BuiltInConverters.ToStringConverter.INSTANCE;
    }

    public final Converter c(Type arg4, Annotation[] arg5) {
        Utils.checkNotNull(arg4, "type == null");
        Utils.checkNotNull(arg5, "annotations == null");
        int v2 = this.converterFactories.size();
        int v1;
        for (v1 = 0; v1 < v2; ++v1) {
            Converter v0 = this.converterFactories.get(v1).d(arg4);
            if (v0 != null) {
                return v0;
            }
        }
        throw new IllegalArgumentException("Could not locate header converter");
    }

    public static final class Builder {
        public Platform platform;
        public Client.Provider clientProvider;
        public HttpUrl baseUrl;
        public RequestInterceptor requestInterceptor;
        public ResponseInterceptor responseInterceptor;
        public List<Converter.Factory> converterFactories;
        public List<CallAdapter.Factory> adapterFactories;
        public Executor httpExecutor;

        public Builder() {
            this(Platform.get());
        }

        private Builder(Platform platform) {
            this.converterFactories = new ArrayList();
            this.adapterFactories = new ArrayList();
            this.platform = platform;
            this.converterFactories.add(new BuiltInConverters());
        }
    }
}

